/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.ndx.majick.properties.util;

import java.beans.PropertyChangeSupport;
import java.beans.VetoableChangeSupport;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.ndx.majick.properties.ComparableProperty;
import org.ndx.majick.properties.ComparableVetoableProperty;
import org.ndx.majick.properties.Property;
import org.ndx.majick.properties.VetoableProperty;
import org.ndx.majick.properties.impl.DefaultComparableProperty;
import org.ndx.majick.properties.impl.DefaultComparableVetoableProperty;
import org.ndx.majick.properties.impl.DefaultProperty;
import org.ndx.majick.properties.impl.DefaultVetoableProperty;

/**
 *
 * @author Maison
 */
public class PropertyUtils {
    /**
     * This logger is both an experiment and a real-time hint engine.
     * It is used across this library to remind us, poor mortals, how to use, or not, this block of code
     */
    public static final Logger GOOD_PRACTICES = Logger.getLogger("org.ndx.makick.majick-properties Best practices reminder");

    public static <Type extends Object> Property<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support) {
        if(GOOD_PRACTICES.isLoggable(Level.FINE))
            GOOD_PRACTICES.fine("use of this method is dsciouraged, since it won't set default value (which will then be set to null). Prefer to call create(Class<Type>, String, PropertyChangeSupport, Type) which will give property a non null default value.");
        return new DefaultProperty<Type>(type, name, support);
    }

    public static <Type extends Object> Property<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, Type value) {
        return new DefaultProperty<Type>(type, name, support, value);
    }

    public static <Type extends Comparable<Type>> ComparableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support) {
        if(GOOD_PRACTICES.isLoggable(Level.FINE))
            GOOD_PRACTICES.fine("use of this method is dsciouraged, since it won't set default value (which will then be set to null). Prefer to call create(Class<Type>, String, PropertyChangeSupport, Type) which will give property a non null default value.");
        return new DefaultComparableProperty<Type>(type, name, support);
    }

    public static <Type extends Comparable<Type>> ComparableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, Type value) {
        return new DefaultComparableProperty<Type>(type, name, support, value);
    }

    public static <Type extends Object> VetoableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport) {
        if(GOOD_PRACTICES.isLoggable(Level.FINE))
            GOOD_PRACTICES.fine("use of this method is dsciouraged, since it won't set default value (which will then be set to null). Prefer to call create(Class<Type>, String, PropertyChangeSupport, VetoableChangeSupport, Type) which will give property a non null default value.");
        return new DefaultVetoableProperty<Type>(type, name, support, vetoSupport);
    }

    public static <Type extends Object> VetoableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport, Type value) {
        return new DefaultVetoableProperty<Type>(type, name, support, vetoSupport, value);
    }

    public static <Type extends Comparable<Type>> ComparableVetoableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport) {
        if(GOOD_PRACTICES.isLoggable(Level.FINE))
            GOOD_PRACTICES.fine("use of this method is dsciouraged, since it won't set default value (which will then be set to null). Prefer to call create(Class<Type>, String, PropertyChangeSupport, VetoableChangeSupport, Type) which will give property a non null default value.");
        return new DefaultComparableVetoableProperty<Type>(type, name, support, vetoSupport);
    }

    public static <Type extends Comparable<Type>> ComparableVetoableProperty<Type> create(Class<? extends Type> type, String name, PropertyChangeSupport support, VetoableChangeSupport vetoSupport, Type value) {
        return new DefaultComparableVetoableProperty<Type>(type, name, support, vetoSupport, value);
    }

	/**
	 * If input class is a primitive one, replace it with its associated obejct type
	 * @param input
	 * @return
	 */
	public static Class<?> unprimitive(Class<?> input) {
		if(input.isPrimitive()) {
			if (GOOD_PRACTICES.isLoggable(Level.FINE))
				GOOD_PRACTICES.log(Level.FINE, "you have created a Property with a primitive type, which is not such a good idea (see joined stack trace to see where you did this mistake). Prefer to use object wrapper for that type.", new Exception());
			if(input==Boolean.TYPE)
				return Boolean.class;
			else if(input==Character.TYPE)
				return Character.class;
			else if(input==Byte.TYPE)
				return Byte.class;
			else if(input==Short.TYPE)
				return Short.class;
			else if(input==Integer.TYPE)
				return Integer.class;
			else if(input==Long.TYPE)
				return Long.class;
			else if(input==Float.TYPE)
				return Float.class;
			else if(input==Double.TYPE)
				return Double.class;
			else if(input==Void.TYPE)
				return Void.class;
			else
				return input;
		} else {
			return input;
		}
	}
}
